/**
 * 
 */
package evolution;

import ca.swank.hq.ai.CachingSmartBoard;

/**
 * @author Alon Segal
 * 
 * Evaluates the player distance from home and the opponent distance from home.
 * Fitness = (2*[opponent distance])/[my distance] +  1/[my distance]
 *
 */
public class BFSBoardEvaluator implements BoardEvaluator {
	
	//private final double distanceWeight = 0.3;
	//private final double wallsWeight = 1 - distanceWeight;
	private final int[] wallValues = new int[] { 0, 4, 7, 10, 13, 16, 19, 21, 23, 25, 26 };

	/**
	 *
	 */
	public BFSBoardEvaluator() {
	}

	/* (non-Javadoc)
	 * @see evolution.BoardFitnessEvaluator#evalFitness(ca.swank.hq.ai.CachingSmartBoard, int)
	 */
	@Override
	public double evalBoard(CachingSmartBoard board, int player) {

		double res = 0;
		int[][] myMapDist = board.getDistanceHomeBoard(player);
		int myXCord = board.getPlayerLocation(player)[0];
		int myYCord = board.getPlayerLocation(player)[1];
		int myDistanceFromHome = myMapDist[myXCord][myYCord];
		int myWalls = board.getPlayerWalls(player);
		
		int[][] opMapDist = board.getDistanceHomeBoard(1-player);
		int opXCord = board.getPlayerLocation(1-player)[0];
		int opYCord = board.getPlayerLocation(1-player)[1];
		int opDistanceFromHome = opMapDist[opXCord][opYCord];
		int opWalls = board.getPlayerWalls(1 - player);
		
		
		if(opWalls == 0 && opDistanceFromHome > myDistanceFromHome) {
			return Double.MAX_VALUE;
		}
		
		if(myWalls == 0 && opDistanceFromHome < myDistanceFromHome) {
			return Double.MIN_VALUE;
		}
		/*
		if(myDistanceFromHome == 1) {
			return Double.MAX_VALUE; 
		}
		
		if(opDistanceFromHome == 1) {
			return Double.MIN_VALUE; 
		}
		*/
		if(myDistanceFromHome == 0) {
			return Double.MAX_VALUE;
		}
		if(opDistanceFromHome == 0) {
			return Double.MIN_VALUE;
		}
		
		/*
		if ((opDistanceFromHome - myDistanceFromHome + 1) > 0 ) {
			factor = 1.0/(opDistanceFromHome - myDistanceFromHome + 1);
		}
		*/
		//res = (((double)opDistanceFromHome * 2.0) / (double)myDistanceFromHome) + (1.0 / (double)myDistanceFromHome);
		//double distW = this.distanceWeight * ((double)opDistanceFromHome - (double)myDistanceFromHome/4.0);
		
		//double distW = this.distanceWeight * ((((double)opDistanceFromHome) + 1.0)/((double)myDistanceFromHome + 1.0));
		//double wallW = this.wallsWeight * ((double)(myWalls + 1.0)/((double)opWalls+1.0));
		//double wallW = this.wallsWeight * ((double)opWalls - (double)myWalls);
		//res = distW + wallW;
				
		res = res - myDistanceFromHome;
	    res = res + wallValues[myWalls];
	    res = res + opDistanceFromHome;
	    res = res - wallValues[opWalls];
		//res = 0.1*((double)opDistanceFromHome ) + 1.0/(double)myDistanceFromHome;
		//System.out.println(res);
		return res;
	}

}
